#define SOURCE_CPU				1
#define SOURCE_DMA				2
#define SOURCE_NONE				3

#define READ_DATA				0x01
#define WRITE_DATA				0x02
#define CACHE_INVALIDATE		0x04
#define CACHE_WRITEBACK			0x08
#define CACHE_READ_TAG			0x10
#define CACHE_WRITE_TAG			0x20
#define CACHE_FILL				0x40
#define CACHE_LOCK				0x80

#define TARGET_ANY				0x00
#define TARGET_L1I				0x01
#define TARGET_L1D				0x02
#define TARGET_L2				0x04
#define TARGET_L3				0x08
#define TARGET_ROM				0x10
#define TARGET_RAM				0x20
#define TARGET_DEV				0x40

#define TARGET_CACHE			0x0F

#define TYPE_VADDR				1			// Virtual address
#define TYPE_PADDR				2			// Physical address
#define TYPE_INDEX				3			// Cache index

#define OPTION_CACHED			0x01		// Use caches
#define OPTION_MAPPED			0x02		// Use TLB
#define OPTION_NOWAIT			0x04		// Do not enqueue
#define OPTION_NOFILL			0x08		// Do not allow cache allocation
#define OPTION_IFETCH			0x10		// Access is instruction fetch

typedef uint8_t		mmu_bool;
typedef uint8_t		mmu_source;
typedef uint8_t		mmu_target;
typedef uint8_t		mmu_action;
typedef uint8_t		mmu_options;
typedef uint8_t		mmu_amode;

static
inline 
uint8_t next_target(mmu_target targets, mmu_target active_target) {
	uint8_t ntargets;
	
	// remove previously accessed targets
	ntargets = targets & ~(active_target | (active_target-1));
	
	// get the lowest bit (i.e. the highest target in the
	// memory hierarchy)
	return ((ntargets & (ntargets-1)) ^ ntargets);
}

struct mmu_op {
	mmu_action		actions;	// Actions to perform
	mmu_options		options;	// Action semantics
	mmu_target		targets;	// Memories to access
	mmu_source		source;		// Unit initiating request
	mmu_amode		a_type;		// Type of address
	
	sim_addr		loc;		// Address
	sim_size		length;		// Bytes of data
	uint8_t			*data;		// Tag/data to read/write

	mmu_target		ctarget;	// current target
	mmu_bool		stalled;	// type of stall, or 0
	mmu_bool		finished;	// 1 if operation has completed
	sim_error		err;		// Return code of operation

	mmu_target		misses;		// bit field of cache misses
	mmu_target		hits;		// bit field of cache hits

	sim_size		delay;		// delay until next action
	sim_size		start;		// cycle operation was started on

	mmu_op			*actual;	// sometimes an op needs pseudo ops
	mmu_op			*pseudo;	// ref to pseudo operation
	mmu_op			*next;		// mmu_ops can be enqueued
};

#define MMU_POLICY_READTHROUGH		0x1		// Simul. memory read/cache store
#define MMU_POLICY_WRITETHROUGH		0x2		// On write, write data back to memory
#define MMU_POLICY_WRITEALLOCATE	0x4		// On write miss read line into cache
#define MMU_POLICY_INSTANT_TLB		0x8

#define MMU_OP_READ					1
#define MMU_OP_WRITE				2
#define MMU_OP_INDEX_INVALIDATE		3
#define MMU_OP_INDEX_LOAD_TAG		4
#define MMU_OP_INDEX_STORE_TAG		5
#define MMU_OP_HIT_INVALIDATE		6
#define MMU_OP_HIT_WB_INVALIDATE	7
#define MMU_OP_ADDR_FILL			8
#define MMU_OP_HIT_WB				9
#define MMU_OP_FETCH_LOCK			10
struct mmu_action {

};
